package com.foreveross.crawl.adapter.sub.impl20140402.v3.britishairways;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.client.HttpClient;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

import com.foreveross.crawl.adapter.PlaneInfoEntityBuilder;
import com.foreveross.crawl.adapter.sub.impl20140402.v3.BritishairwaysAdapter;
import com.foreveross.crawl.common.exception.self.PageErrorResultException;
import com.foreveross.crawl.common.exception.self.SourceDataParseNullException;
import com.foreveross.crawl.common.util.RegHtmlUtil;
import com.foreveross.crawl.domain.airfreight.CabinEntity;
import com.foreveross.crawl.domain.airfreight.doub.DoublePlaneInfoEntity;
import com.foreveross.crawl.domain.airfreight.doub.ReturnCabinEntity;
import com.foreveross.crawl.domain.airfreight.doub.ReturnDoublePlaneInfoEntity;
import com.foreveross.crawl.exception.NoTicketException;
import com.foreveross.crawl.util.DateUtil;
import com.foreveross.taskservice.common.bean.TaskModel;
import com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException;
import com.gargoylesoftware.htmlunit.HttpMethod;
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.WebRequest;
import com.gargoylesoftware.htmlunit.html.DomElement;
import com.gargoylesoftware.htmlunit.html.HtmlAnchor;
import com.gargoylesoftware.htmlunit.html.HtmlForm;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import com.gargoylesoftware.htmlunit.html.HtmlRadioButtonInput;
import com.gargoylesoftware.htmlunit.html.HtmlSubmitInput;
import com.gargoylesoftware.htmlunit.util.NameValuePair;
import com.google.common.collect.Maps;

/**
 * 英国航空公司国际往返
 * 根据需求全部为直飞
 * @author luofangyi
 *
 */
public class BritishairwaysInernationRoundTrip {

	private BritishairwaysAdapter baAdapter;
	private TaskModel taskQueue;
	private final int retryCount = 3;
	private WebClient webClient;
	private HttpClient httpClient ;
	private boolean isHomePageEnter = true;	
	protected Log logger = LogFactory.getLog(getClass());
	public BritishairwaysInernationRoundTrip(BritishairwaysAdapter baAdapter, TaskModel taskQueue){
		
		this.baAdapter = baAdapter; 
		this.taskQueue = taskQueue;
		this.webClient = baAdapter.getWebClientByFF();
		this.httpClient=baAdapter.getHttpClient();
		isHomePageEnter();
	}
	
	/**
	 * 用于随机从入口进入查询结果页
	 */
	private void isHomePageEnter(){
		
		Random random = new Random();
		int number = random.nextInt(10);
		if(number % 2 == 0){
			isHomePageEnter = true;
		} else {
			isHomePageEnter = false;
		}
	}
	
	public List<DoublePlaneInfoEntity> fetchData() throws Exception {

		String researchHtml = "";
		HtmlPage page = null;
		HtmlForm form = null;
		if (isHomePageEnter) {
			page = webClient
					.getPage("http://www.britishairways.com/travel/home/public/zh_cn");
			form = page.getForms().get(6);
		} else {
			page = webClient
					.getPage("http://www.britishairways.com/travel/fx/public/zh_cn");
			form = page.getFormByName("plan_trip");
		}
		
		baAdapter.appendPageContents(page.asXml());
		baAdapter.hasWebClientRedirectEnabled(webClient);
		HtmlPage researchPage = webClient.getPage(this.getResearchWebRequest("http://www.britishairways.com/travel/fx/public/zh_cn", form,1));
//		HtmlPage researchPage = webClient
//				.getPage("http://www.britishairways.com/travel/fx/public/zh_cn?"
//						+ this.spliteFirstLayParams(form));
		// 阻塞线程js执行完毕或者达到指定时间
		webClient.waitForBackgroundJavaScriptStartingBefore(60000);
		researchHtml = researchPage.asXml();
		baAdapter.appendPageContents(researchHtml);
		
		if (researchHtml.length() < 100000) {
			HtmlAnchor anchor = researchPage.getAnchorByText("继续");
			researchPage = anchor.click();
			if(researchPage.asXml().length() < 100000)
				throw new PageErrorResultException("onclick后，获取的查询结果页面错误");
		}		
		
//		//test**************************************
//		HtmlPage researchPage2	= webClient.getPage("https://www.britishairways.com/travel/fx/public/zh_cn?source=continue&continue=%E7%BB%A7%E7%BB%AD&eId=111075&eIdSortBy=&inbound=1&inbound=W-1&inboundCabin=W&inboundHLAFlag=true&isHBOPage=false&outbound=1&outbound=C-1&outboundCabin=C&outboundHLAFlag=true&selectedHboFare=false&selectedHboFare=false&syncIndicator-inbound=on&syncIndicator-outbound=on");//webClient.getPage(this.getResearchWebRequest("https://www.britishairways.com/travel/fx/public/zh_cn", researchPage.getFormByName("flightList"),2));
//		webClient.waitForBackgroundJavaScriptStartingBefore(10000);
//		researchPage2=webClient.getPage("https://www.britishairways.com/travel/fx/public/zh_cn?eId=111011&timestamp="+System.currentTimeMillis()+"&source=continue&source=continue");
//		System.err.println(researchPage2.asXml());
		
		return parseHtml(researchPage);
	}
	
	private WebRequest getResearchWebRequest(String urlStr, HtmlForm form,int f) throws MalformedURLException{
		
		URL url = new URL(urlStr);
		WebRequest webRequest = new WebRequest(url, HttpMethod.POST);
		List<NameValuePair> reqParam = new ArrayList<NameValuePair>();
		Map<String, String> pairMap =null;
		if(f==1){
			 pairMap = this.spliteFirstLayMap(form);
		}else{
			 pairMap = this.spliteFirstLayMap2(form);
		}
		
		
		Set<String> keySet = pairMap.keySet();
		for(String key : keySet){
			reqParam.add(new NameValuePair(key, pairMap.get(key)));
		}
		webRequest.setRequestParameters(reqParam);
		return webRequest;
	}
	
	private WebRequest getResearchDetailWebRequest(String urlStr, HtmlForm form, String outBoundValue, String inBoundValue) throws MalformedURLException{
		
		URL url = new URL(urlStr);
		WebRequest webRequest = new WebRequest(url, HttpMethod.POST);
		List<NameValuePair> reqParam = new ArrayList<NameValuePair>();
		Map<String, String> pairMap = this.spliteResearchDetailMap(form);
		Set<String> keySet = pairMap.keySet();
		reqParam.add(new NameValuePair("source", "continue"));
		reqParam.add(new NameValuePair("outbound", outBoundValue));
		reqParam.add(new NameValuePair("inbound", inBoundValue));
		for(String key : keySet){
			reqParam.add(new NameValuePair(key, pairMap.get(key)));
		}
		webRequest.setRequestParameters(reqParam);
		return webRequest;
	}
	
	private Map<String, String> spliteResearchDetailMap(HtmlForm form) {
		Map<String, String> map = new HashMap<String, String>();
		
		map.put("eId", form.getInputByName("eId").getValueAttribute());
		map.put("eIdSortBy", form.getInputByName("eIdSortBy").getValueAttribute());
		map.put("outboundCabin", form.getInputByName("outboundCabin").getValueAttribute());
		map.put("outbound", form.getInputByName("outbound").getValueAttribute());
		map.put("selectedHboFare", form.getInputByName("selectedHboFare").getValueAttribute());
		map.put("isHBOPage", form.getInputByName("isHBOPage").getValueAttribute());
		map.put("outboundHLAFlag", form.getInputByName("outboundHLAFlag").getValueAttribute());
		map.put("inboundCabin", form.getInputByName("inboundCabin").getValueAttribute());
		map.put("inbound", form.getInputByName("inbound").getValueAttribute());
		map.put("selectedHboFare", form.getInputByName("selectedHboFare").getValueAttribute());
		map.put("inboundHLAFlag", form.getInputByName("inboundHLAFlag").getValueAttribute());
		return map;
	}

	/**
	 * 解析往返数据，放入DoublePlaneInfoEntity模型
	 * @param html
	 * @return
	 * @throws Exception 
	 */
	public List<DoublePlaneInfoEntity> parseHtml(HtmlPage researchPage) throws Exception{
	
		List<DoublePlaneInfoEntity> list = new ArrayList<DoublePlaneInfoEntity>();
		DoublePlaneInfoEntity doubleEntity = null;
		doubleEntity = parseOutBound(researchPage, doubleEntity);
		doubleEntity = parseInBound(researchPage, doubleEntity);
		try{
		//暂时只取最低价的税费
			if(baAdapter.isGrab){
				Document researchDoc = Jsoup.parse(researchPage.asXml());
				Element outBoundFlightList = researchDoc.getElementById("outBoundFlightList");//离港（去程）
				Element inBoundFlightList = researchDoc.getElementById("inBoundFlightList");//入港（回程）
				Map<String,String> GcabinTypeCode=Maps.newHashMap();//存储去程舱位对应价格
				List<String> GpriceList=new ArrayList<String>();
				Map<String,String> BcabinTypeCode=Maps.newHashMap();//存储回程舱位对应
				List<String> BpriceList=new ArrayList<String>();
				//分析出去程最低价和回程最低价的对应仓位
				//去程
				Elements col0_1 = outBoundFlightList.select("td.price-M").select("span.priceSelection");
				if(col0_1 != null && col0_1.size() != 0){
					Map<String,String> mapStr=getCabinPrice(col0_1);
					GcabinTypeCode.put(mapStr.keySet().iterator().next().toString(),mapStr.values().iterator().next().toString());
					GpriceList.add(mapStr.keySet().iterator().next().toString());
				}
				Elements col0_2 = outBoundFlightList.select("td.price-W").select("span.priceSelection");
				if(col0_1 != null && col0_2.size() != 0){
					Map<String,String> mapStr=getCabinPrice(col0_2);
					GcabinTypeCode.put(mapStr.keySet().iterator().next().toString(),mapStr.values().iterator().next().toString());
					GpriceList.add(mapStr.keySet().iterator().next().toString());
				}
				Elements col0_3 = outBoundFlightList.select("td.price-C").select("span.priceSelection");
				if(col0_3 != null && col0_3.size() != 0){
					Map<String,String> mapStr=getCabinPrice(col0_3);
					GcabinTypeCode.put(mapStr.keySet().iterator().next().toString(),mapStr.values().iterator().next().toString());
					GpriceList.add(mapStr.keySet().iterator().next().toString());
				}
				
				//回程
				Elements col1_1 = inBoundFlightList.select("td.price-M").select("span.priceSelection");
				if(col1_1 != null && col1_1.size() != 0){
					Map<String,String> mapStr=getCabinPrice(col1_1);
					BcabinTypeCode.put(mapStr.keySet().iterator().next().toString(),mapStr.values().iterator().next().toString());
					BpriceList.add(mapStr.keySet().iterator().next().toString());
				}
				Elements col1_2 = inBoundFlightList.select("td.price-W").select("span.priceSelection");
				if(col1_2 != null && col1_2.size() != 0){
					Map<String,String> mapStr=getCabinPrice(col1_2);
					BcabinTypeCode.put(mapStr.keySet().iterator().next().toString(),mapStr.values().iterator().next().toString());
					BpriceList.add(mapStr.keySet().iterator().next().toString());
				}
				Elements col1_3 = inBoundFlightList.select("td.price-C").select("span.priceSelection");
				if(col1_3 != null && col1_3.size() != 0){
					Map<String,String> mapStr=getCabinPrice(col1_3);
					BcabinTypeCode.put(mapStr.keySet().iterator().next().toString(),mapStr.values().iterator().next().toString());
					BpriceList.add(mapStr.keySet().iterator().next().toString());
				}
				
				//分析出对应ID
				HtmlForm taxForm=researchPage.getFormByName("flightList");
				String eId=taxForm.getInputByName("eId").getValueAttribute();
				
				
	//			String outBoundValue = this.onclickLowestPriceRadioValue(researchPage, outBoundFlightList);
	//			String inBoundValue = this.onclickLowestPriceRadioValue(researchPage, inBoundFlightList);
	//			HtmlPage detailPage_1 = this.onclickLowestPriceRadio(researchPage, inBoundFlightList);
	//			HtmlForm form = detailPage_1.getFormByName("flightList");
	//			String outBoundValue = form.getInputByName("").getValueAttribute();
	//			String inBoundValue = form.getInputByName("").getValueAttribute();
	//			HtmlForm form = researchPage.getFormByName("flightList");
	//			String urlStr = "https://www.britishairways.com/travel/fx/public/zh_cn";
	//			webClient.getOptions().setJavaScriptEnabled(false);
	//			webClient.getOptions().setRedirectEnabled(f);
	//			webClient.setAjaxController(null);
	//			HtmlPage detailPage = webClient.getPage(this.getResearchDetailWebRequest(urlStr, form, outBoundValue, inBoundValue));
	//			System.out.println("#########start##############");
	//			System.out.println(detailPage.asXml());
	//			System.out.println("#########end##############");
				
				//**********取税费信息****************************
				HtmlPage taxPages=null;
				if(BcabinTypeCode.size()>0 && GcabinTypeCode.size()>0 && BpriceList.size()>0 && GpriceList.size()>0){
					String outCode="",inCode="";
					Collections.sort(BpriceList);
					Collections.sort(GpriceList);
					outCode=GcabinTypeCode.get(GpriceList.get(GpriceList.size()-1));
					inCode=BcabinTypeCode.get(BpriceList.get(BpriceList.size()-1));
					if(!"".equals(inCode) && inCode !=null && !"".equals(outCode) && outCode!=null){
						try{
							logger.info("开始执行拿税费操作....");
							String url="https://www.britishairways.com/travel/fx/public/zh_cn?source=continue&continue=%E7%BB%A7%E7%BB%AD&eId="+eId+"" +
									"&eIdSortBy=&inbound=1&inbound="+inCode+"&inboundCabin="+inCode.split("-")[0]+"" +
											"&inboundHLAFlag=true&isHBOPage=false&outbound=1&outbound="+outCode+"&outboundCabin="+outCode.split("-")[0]+"&outboundHLAFlag=true&selectedHboFare=false" +
											"&selectedHboFare=false&syncIndicator-inbound=on&syncIndicator-outbound=on";
							taxPages = webClient.getPage(url);
//							webClient.getOptions().setTimeout(300000);
							webClient.waitForBackgroundJavaScriptStartingBefore(10000);
							taxPages=webClient.getPage("https://www.britishairways.com/travel/fx/public/zh_cn?eId=111011&timestamp="+System.currentTimeMillis()+"&source=continue&source=continue");
//							webClient.getOptions().setTimeout(300000);
							baAdapter.appendPageContents(taxPages.asXml());//存储税收信息
						//	System.err.println(taxPages.asXml());
						}catch (Exception e) {
							logger.info("抓取税费失败！");
							list.add(doubleEntity);
							return baAdapter.dealToEntityAndReturnEntity(list);
						}
					}
					
				}
				
				if(taxPages.asXml().length()>500  && taxPages !=null ){
					Document doc = Jsoup.parse(taxPages.asXml());
					Element priceBreakdown = doc.getElementById("priceBreakdown");
					Elements nakedPrice = priceBreakdown.select("tr.nowrap");
					String pricesInfo = nakedPrice.text();
					String prices = pricesInfo.substring(pricesInfo.indexOf("CNY")).replaceAll(",","").replaceAll(" ", "");
					String[] priceArray = prices.split("CNY");
					String totalLowestPrice = null;//最低裸价
					String totalLowestTaxesPrice = null;//最低税费价
					String sumLowestPrice = null;//最低合计价
					String totalHightPrice = null;//最高裸价
					String totalhightTaxesPrice = null;//最高税费价
					String sumHightPrice = null;//最高合计价
					if(priceArray.length == 4){
						totalLowestPrice = priceArray[1];
						totalLowestTaxesPrice = priceArray[2];//最低税费价
						sumLowestPrice = priceArray[3];//最低合计价
					}
					//
					int temp=doubleEntity.getReturnPlaneInfos().size();
					if(temp>0){
						Set<ReturnDoublePlaneInfoEntity>  reSets=doubleEntity.getReturnPlaneInfos();
						//根据此适配器实际抓取情况，现在只有一条回程数据
						for(ReturnDoublePlaneInfoEntity reE:reSets){
							for(ReturnCabinEntity reCabinsE:reE.getReturnCabins()){
								reCabinsE.setTaxesPrice((totalLowestTaxesPrice != null && !totalLowestTaxesPrice.trim().equals("")) ? Double.parseDouble(totalLowestTaxesPrice) : null);
								reCabinsE.setOriginalPrice(reCabinsE.getPrice()+reCabinsE.getTaxesPrice());
							}
							reE.setTotalLowestPrice((totalLowestPrice != null && !totalLowestPrice.trim().equals("")) ? Double.parseDouble(totalLowestPrice) : null);
							reE.setSumLowestPrice((sumLowestPrice != null && !sumLowestPrice.trim().equals("")) ? Double.parseDouble(sumLowestPrice) : null);
							reE.setTotalLowestTaxesPrice((totalLowestTaxesPrice != null && !totalLowestTaxesPrice.trim().equals("")) ? Double.parseDouble(totalLowestTaxesPrice) : null);
							
							reE.setTotalHighestPrice((totalLowestPrice != null && !totalLowestPrice.trim().equals("")) ? Double.parseDouble(totalLowestPrice) : null);
							reE.setSumHighestPrice((sumLowestPrice != null && !sumLowestPrice.trim().equals("")) ? Double.parseDouble(sumLowestPrice) : null);
							reE.setTotalHighestTaxesPrice((totalLowestTaxesPrice != null && !totalLowestTaxesPrice.trim().equals("")) ? Double.parseDouble(totalLowestTaxesPrice) : null);
						}
					}
					for(CabinEntity tCb:doubleEntity.getCabins()){
						tCb.setTaxesPrice((totalLowestTaxesPrice != null && !totalLowestTaxesPrice.trim().equals("")) ? Double.parseDouble(totalLowestTaxesPrice) : null);
						tCb.setOriginalPrice(tCb.getTaxesPrice()+tCb.getPrice());
					}
					
					doubleEntity.setTotalLowestPrice((totalLowestPrice != null && !totalLowestPrice.trim().equals("")) ? Double.parseDouble(totalLowestPrice) : null);
					doubleEntity.setTotalLowestTaxesPrice((totalLowestTaxesPrice != null && !totalLowestTaxesPrice.trim().equals("")) ? Double.parseDouble(totalLowestTaxesPrice) : null);
					doubleEntity.setSumLowestPrice((sumLowestPrice != null && !sumLowestPrice.trim().equals("")) ? Double.parseDouble(sumLowestPrice) : null);
					
					doubleEntity.setTotalHighestPrice((totalLowestPrice != null && !totalLowestPrice.trim().equals("")) ? Double.parseDouble(totalLowestPrice) : null);
					doubleEntity.setTotalHighestTaxesPrice((totalLowestTaxesPrice != null && !totalLowestTaxesPrice.trim().equals("")) ? Double.parseDouble(totalLowestTaxesPrice) : null);
					doubleEntity.setSumHighestPrice((sumLowestPrice != null && !sumLowestPrice.trim().equals("")) ? Double.parseDouble(sumLowestPrice) : null);
				}
			}
		}catch (Exception e) {
			logger.info("税费分析失败！");
			list.add(doubleEntity);
			return baAdapter.dealToEntityAndReturnEntity(list);
			
			
		}
		list.add(doubleEntity);
		
		return baAdapter.dealToEntityAndReturnEntity(list);
	}
	
	
	public Map<String,String> getCabinPrice(Elements col1){
		Map<String,String> priceMap=Maps.newHashMap();
		String value=col1.get(0).getElementsByTag("input").get(0).attr("value").replaceAll(" ", "");
		String key=RegHtmlUtil.regStr(col1.get(0).text(),"(\\d{1,10})").replaceAll(" ", "");
		priceMap.put(key, value);
		return priceMap;
	}
	
	
//	public List<DoublePlaneInfoEntity> parseHtml(HtmlPage researchPage) throws Exception{
//		
//		List<DoublePlaneInfoEntity> list = new ArrayList<DoublePlaneInfoEntity>();
//		DoublePlaneInfoEntity doubleEntity = null;
////		doubleEntity = parseOutBound(researchPage, doubleEntity);
////		doubleEntity = parseInBound(researchPage, doubleEntity);
//		
//		if(baAdapter.isGrab){
//			Document researchDoc = Jsoup.parse(researchPage.asXml());
//			Element inBoundFlightList = researchDoc.getElementById("inBoundFlightList");
//			
////			String inBoundValue = this.onclickLowestPriceRadioValue(researchPage, inBoundFlightList);
//			
////			HtmlForm form = researchPage.getFormByName("flightList");
////			String urlStr = "https://www.britishairways.com/travel/fx/public/zh_cn";
//
//			HtmlPage detailPage_1 = this.onclickLowestPriceRadio(researchPage, inBoundFlightList);
//			HtmlForm form = detailPage_1.getFormByName("flightList");
////			HtmlPage detailPage = form.click();
//			final HtmlSubmitInput button = form.getInputByName("continue");
//			HtmlPage detailPage = button.click();
//			Thread.sleep(3000L);
//			System.out.println("#########start##############");
//			System.out.println(detailPage.asXml());
//			System.out.println("#########end##############");
//			
////			System.out.println("^^^^^^^^^HtmlSubmitInput^^^^^^^start^^^^^^^^^^^^^^^^");
////			System.out.println(detailPage_2.asXml());
////			System.out.println("^^^^^^^^^^^^^^^^end^^^^^^^^^^^^^^^^");
//			
//			Document doc = Jsoup.parse(detailPage.asXml());
//			Element priceBreakdown = doc.getElementById("priceBreakdown");
//			Elements nakedPrice = priceBreakdown.select("tr.nowrap");
//			String pricesInfo = nakedPrice.text();
//			String prices = pricesInfo.substring(pricesInfo.indexOf("CNY")).replaceAll(",","").replaceAll(" ", "");
//			String[] priceArray = prices.split("CNY");
//			String totalLowestPrice = null;//最低裸价
//			String totalLowestTaxesPrice = null;//最低税费价
//			String sumLowestPrice = null;//最低合计价
//			if(priceArray.length == 4){
//				totalLowestPrice = priceArray[1];
//				totalLowestTaxesPrice = priceArray[2];//最低税费价
//				sumLowestPrice = priceArray[3];//最低合计价
//			}
//			doubleEntity.setTotalLowestPrice((totalLowestPrice != null && !totalLowestPrice.trim().equals("")) ? Double.parseDouble(totalLowestPrice) : null);
//			doubleEntity.setTotalLowestTaxesPrice((totalLowestTaxesPrice != null && !totalLowestTaxesPrice.trim().equals("")) ? Double.parseDouble(totalLowestTaxesPrice) : null);
//			doubleEntity.setSumLowestPrice((sumLowestPrice != null && !sumLowestPrice.trim().equals("")) ? Double.parseDouble(sumLowestPrice) : null);
//		}
//		list.add(doubleEntity);
//		return list;
//	}

	/**
	 * 解析去程数据
	 * @param doc
	 * @param doubleEntity
	 * @throws Exception
	 */
	private DoublePlaneInfoEntity parseOutBound(HtmlPage researchPage, DoublePlaneInfoEntity doubleEntity) throws Exception {
	
		Document doc = Jsoup.parse(researchPage.asXml());
		Element outBoundFlightList = doc.getElementById("outBoundFlightList");
		if(outBoundFlightList == null)
			throw new PageErrorResultException("获取去程页面信息错误");
		return obtainFlightInfo(researchPage, doubleEntity, outBoundFlightList, baAdapter.GO);
	}
	
	/**
	 * 解析回程数据
	 * @param doc
	 * @param doubleEntity
	 * @throws Exception
	 */
	private DoublePlaneInfoEntity parseInBound(HtmlPage researchPage, DoublePlaneInfoEntity doubleEntity) throws Exception {
		
		Document doc = Jsoup.parse(researchPage.asXml());
		Element inBoundFlightList = doc.getElementById("inBoundFlightList");
		if(inBoundFlightList == null)
			throw new PageErrorResultException("获取回程页面信息错误");
		return obtainFlightInfo(researchPage, doubleEntity, inBoundFlightList, baAdapter.BACK);
	}
	
	/**
	 * 抓取(去/回程)航班信息
	 * @param boundFlightList
	 * @param type
	 * @throws Exception 
	 */
	private DoublePlaneInfoEntity obtainFlightInfo(HtmlPage researchPage, DoublePlaneInfoEntity doubleEntity, Element boundFlightList, int type)
			throws Exception {
		Elements flightPopUp = boundFlightList.select("a.flightPopUp");
		if(flightPopUp == null || flightPopUp.size() == 0){
			throw new PageErrorResultException("获取航班详情页面信息错误");
		}
		String flightNo = null;
		String carrierKey = null;
		String carrierName = null;
		String carrierFullName = null;
		String flightType = null;
		Date startTime = null;//起飞时间 
		Date endTime = null;//到达时间
		String cabinType = null;//仓位等级
		String subCabinName = null;//子舱名称
		Long flightDuration = 0L;//飞行总时长
		String totalLowestPrice = null;//最低裸价
		String totalLowestTaxesPrice = null;//最低税费价
		String sumLowestPrice = null;//最低合计价
		String lastSeatInfo = null;//剩余舱位信息
		List<DomElement> flightDetailsList = null;
		
		try {
			HtmlPage popUpPage = parseFlightPopUp(flightPopUp);
			flightDetailsList = popUpPage.getElementsByTagName("td");//.getElementsByName("td");
			if(flightDetailsList != null && flightDetailsList.size() == 10){
				flightNo = flightDetailsList.get(0).asText().split(" ")[0];
				carrierFullName = flightDetailsList.get(1).asText();
				if(carrierFullName.equals("British Airways") || carrierFullName == "British Airways"){
					carrierName = "BA";
				}
				String fromInfo = flightDetailsList.get(2).asXml();
//				fromCityName = baAdapter.getPatternString(fromInfo, "<td class=\"value\">(.+?)<br/>");
				String fromTime = baAdapter.getPatternString(fromInfo, "<br/>(.+?)</td>");
				startTime = baAdapter.convertStrToDate(fromTime);
				
				String toInfo = flightDetailsList.get(3).asXml();
//				toCityName = baAdapter.getPatternString(toInfo, "<td class=\"value\">(.+?)<br/>");
				String toTime = baAdapter.getPatternString(toInfo, "<br/>(.+?)</td>");
				endTime = baAdapter.convertStrToDate(toTime);
				
				String flyTime = flightDetailsList.get(5).asText();//飞行时间     形如: 10hrs 55mins
				flightDuration = baAdapter.convertStrToLong(flyTime);
				flightType = flightDetailsList.get(6).asText();
				
			}
		} catch (Exception e1) {
			e1.printStackTrace();
		}
		
		List<Object> outList = obtainLowestPriceAndLeaveInfo(researchPage, boundFlightList, type);
//		if(outList.get(0) == null || (Integer)outList.get(0) == -1){
//			if(type == baAdapter.GO){
//				throw new NoTicketException("去程票已售完");
//			} else {
//				throw new NoTicketException("回程票已售完");
//			}
//		}
		
		totalLowestPrice = ((Integer)outList.get(0)).toString();
		if(outList.size() > 1){
			lastSeatInfo = baAdapter.replaceSpecialCharacters((String)outList.get(1));
		}
		
		ReturnDoublePlaneInfoEntity retEntity = null;
		if(type == baAdapter.GO){
			doubleEntity = PlaneInfoEntityBuilder.buildPlaneInfo(
					this.taskQueue, carrierKey, carrierName, carrierFullName,
					DateUtil.date2String(startTime, "yyyy-MM-dd hh:mm"),
					DateUtil.date2String(endTime, "yyyy-MM-dd hh:mm"),
					flightNo, null/*totalLowestPrice.toString()*/, null, null, flightType,
					DoublePlaneInfoEntity.class);
			doubleEntity.setFlightDuration(flightDuration);
			doubleEntity.setTotalLowestTaxesPrice((totalLowestTaxesPrice != null && !totalLowestTaxesPrice.trim().equals("")) ? Double.parseDouble(totalLowestTaxesPrice) : null);
			doubleEntity.setSumLowestPrice((sumLowestPrice != null && !sumLowestPrice.trim().equals("")) ? Double.parseDouble(sumLowestPrice) : null);
			
			doubleEntity.getCabins().addAll(this.getAllOutCabinEntityInfo(flightDetailsList, boundFlightList));
		} else {
			retEntity = PlaneInfoEntityBuilder.buildPlaneInfo(
					this.taskQueue, carrierKey, carrierName, carrierFullName,
					DateUtil.date2String(startTime, "yyyy-MM-dd hh:mm"),
					DateUtil.date2String(endTime, "yyyy-MM-dd hh:mm"),
					flightNo, null/*totalLowestPrice.toString()*/, null, null, flightType,
					ReturnDoublePlaneInfoEntity.class);
			retEntity.setFlightDuration(flightDuration);
			doubleEntity.setTotalLowestTaxesPrice((totalLowestTaxesPrice != null && !totalLowestTaxesPrice.trim().equals("")) ? Double.parseDouble(totalLowestTaxesPrice) : null);
			doubleEntity.setSumLowestPrice((sumLowestPrice != null && !sumLowestPrice.trim().equals("")) ? Double.parseDouble(sumLowestPrice) : null);
//			ReturnCabinEntity cabin = new ReturnCabinEntity();
//			cabin.setCabinType(cabinType);
//			cabin.setSubCabinName(subCabinName);
//			cabin.setLastSeatInfo(lastSeatInfo);
			retEntity.getReturnCabins().addAll(this.getAllInReturnCabinEntityInfo(flightDetailsList, boundFlightList));
			if(doubleEntity != null){
				if(retEntity == null){
					throw new SourceDataParseNullException("回程数据解析为空");
				} else {
					doubleEntity.getReturnPlaneInfos().add(retEntity);
				}
			} else {
				throw new SourceDataParseNullException("去程数据解析为空");
			}
		}
		return doubleEntity;
	}
	
	private List<CabinEntity> getAllOutCabinEntityInfo(List<DomElement> flightDetailsList, Element boundFlightList) throws NoTicketException, IOException{
		List<CabinEntity> list = new ArrayList<CabinEntity>();
		Map<Integer, List<String>> cabinMap = this.obtainAllCabinLowestPriceAndLeaveInfo(boundFlightList, baAdapter.GO);
		Set<Integer> keySet = cabinMap.keySet();
		List<String> priceAndLeaveInfo = null;//new ArrayList<String>();
		List<String> cabinInfo = null;
		for(Integer key : keySet){
			priceAndLeaveInfo = cabinMap.get(key);
			cabinInfo = this.obtainCabinInfo(flightDetailsList, key);
			CabinEntity cabin = new CabinEntity();
			cabin.setCabinType((cabinInfo != null && cabinInfo.size() > 0) ? cabinInfo.get(0) : null);
			cabin.setSubCabinName((cabinInfo != null && cabinInfo.size() == 2) ? cabinInfo.get(1) : null);
			cabin.setPrice((priceAndLeaveInfo != null && priceAndLeaveInfo.size() > 0) ? Double.parseDouble(priceAndLeaveInfo.get(0)) : null);//此舱位价格就是totalLowestPrice
			cabin.setLastSeatInfo((priceAndLeaveInfo != null && priceAndLeaveInfo.size() == 2) ? priceAndLeaveInfo.get(1) : null);
			list.add(cabin);
		}
		return list;
	}
	
	private List<ReturnCabinEntity> getAllInReturnCabinEntityInfo(List<DomElement> flightDetailsList, Element boundFlightList) throws NoTicketException, IOException{
		List<ReturnCabinEntity> list = new ArrayList<ReturnCabinEntity>();
		Map<Integer, List<String>> cabinMap = this.obtainAllCabinLowestPriceAndLeaveInfo(boundFlightList, baAdapter.GO);
		Set<Integer> keySet = cabinMap.keySet();
		List<String> priceAndLeaveInfo = null;//new ArrayList<String>();
		List<String> cabinInfo = null;
		for(Integer key : keySet){
			priceAndLeaveInfo = cabinMap.get(key);
			cabinInfo = this.obtainCabinInfo(flightDetailsList, key);
			ReturnCabinEntity cabin = new ReturnCabinEntity();
			cabin.setCabinType((cabinInfo != null && cabinInfo.size() > 0) ? cabinInfo.get(0) : null);
			cabin.setSubCabinName((cabinInfo != null && cabinInfo.size() == 2) ? cabinInfo.get(1) : null);
			cabin.setPrice((priceAndLeaveInfo != null && priceAndLeaveInfo.size() > 0) ? Double.parseDouble(priceAndLeaveInfo.get(0)) : null);//此舱位价格就是totalLowestPrice
			cabin.setLastSeatInfo((priceAndLeaveInfo != null && priceAndLeaveInfo.size() == 2) ? priceAndLeaveInfo.get(1) : null);
			list.add(cabin);
		}
		return list;
	}
	
	private List<String> obtainCabinInfo(List<DomElement> flightDetailsList, Integer step){
		List<String> list = new ArrayList<String>();
		String subCabinName = null, cabinType = null;
		//子舱选取优先顺序：经济客舱子舱、高级经济客舱、公务客舱
		if(step > 0){
			subCabinName = flightDetailsList.get(step).asText();
			if(step == 7){
				cabinType = "高级经济客舱";
			} else if(step == 8){
				cabinType = "经济客舱";
			} else if(step == 9){
				cabinType = "公务客舱";
			}
		}
		list.add(cabinType);
		list.add(subCabinName);
		return list;
	}
	
	/**
	 * 获取最低价及剩余座位信息
	 * @param researchPage 查询结果页
	 * @param boundFlightList 待筛选的Element元素
	 * @param type 往返程类型
	 * @return
	 * @throws NoTicketException 
	 * @throws IOException 
	 */
	private List<Object> obtainLowestPriceAndLeaveInfo(HtmlPage researchPage, Element boundFlightList, int type) throws NoTicketException, IOException {
		List<Object> retList = new ArrayList<Object>();
		int[] colPrice = new int[]{-1, -1 , -1};
		String[] colLeave = new String[]{"", "", ""};
		Elements col1 = boundFlightList.select("td.price-M").select("span.priceSelection");
		int max, min;
		max = min = colPrice[0];
		String maxLeave, minLeave;
		maxLeave = minLeave = colLeave[0];
		boolean isThrows = true;
		
		if(col1 != null && col1.size() != 0){
			Elements leave1 = boundFlightList.select("td.price-M").select("span.threelimitedSeatAvailMessage");
			colPrice[0] = Integer.parseInt(col1.text().replace("CNY", "").trim());
			colLeave[0] = leave1.text();
			min = colPrice[0];
			isThrows = false;
		}
		
		Elements col2 = boundFlightList.select("td.price-W").select("span.priceSelection");
		if(col2 != null && col2.size() != 0){
			Elements leave2 = boundFlightList.select("td.price-W").select("span.threelimitedSeatAvailMessage");
			colPrice[1] = Integer.parseInt(col2.text().replace("CNY", "").trim());
			colLeave[1] = leave2.text();
			min = colPrice[1];
			isThrows = false;
		}
		
		Elements col3 = boundFlightList.select("td.price-C").select("span.priceSelection");
		
		if(col3 != null && col3.size() != 0){
			Elements leave3 = boundFlightList.select("td.price-C").select("span.threelimitedSeatAvailMessage");
			colPrice[2] = Integer.parseInt(col3.text().replace("CNY", "").trim());
			colLeave[2] = leave3.text();
			min = colPrice[2];
			isThrows = false;
		}
		if(isThrows){
			if(type == baAdapter.GO){
				throw new NoTicketException("去程票已售完");
			} else {
				throw new NoTicketException("回程票已售完");
			}
		}
		
		for(int i = 1; i < colPrice.length; i++){
			if(colPrice[i] > max){
				max = colPrice[i];
				maxLeave = colLeave[i];
			}
		}
		
		//从下标为0开始
		for(int i = 0; i < colPrice.length; i++){
			
			if(colPrice[i] < min && colPrice[i] > 0){
				min = colPrice[i];
				minLeave = colLeave[i];
			}
		}
		
		retList.add(min);
		retList.add(minLeave);
//		retList.add(max);
//		retList.add(maxLeave);
		
		return retList;
	}
	
	private Map<Integer, List<String>> obtainAllCabinLowestPriceAndLeaveInfo(Element boundFlightList, int type) throws NoTicketException, IOException {
		Map<Integer, List<String>> retMap = new HashMap<Integer, List<String>>();
		Elements col1 = boundFlightList.select("td.price-M").select("span.priceSelection");
		boolean isThrows = true;
		List<String> infoList = null;
		if(col1 != null && col1.size() != 0){
			Elements leave1 = boundFlightList.select("td.price-M").select("span.threelimitedSeatAvailMessage");
			infoList = new ArrayList<String>();
			infoList.add(col1.text().replace("CNY", "").trim());
			infoList.add(leave1.text());
			retMap.put(baAdapter.ECONOMY, infoList);
			isThrows = false;
		}
		
		Elements col2 = boundFlightList.select("td.price-W").select("span.priceSelection");
		if(col2 != null && col2.size() != 0){
			Elements leave2 = boundFlightList.select("td.price-W").select("span.threelimitedSeatAvailMessage");
			infoList = new ArrayList<String>();
			infoList.add(col2.text().replace("CNY", "").trim());
			infoList.add(leave2.text());
			retMap.put(baAdapter.WORLDTRAVELLERPLUS, infoList);
			isThrows = false;
		}
		
		Elements col3 = boundFlightList.select("td.price-C").select("span.priceSelection");
		
		if(col3 != null && col3.size() != 0){
			Elements leave3 = boundFlightList.select("td.price-C").select("span.threelimitedSeatAvailMessage");
			infoList = new ArrayList<String>();
			infoList.add(col3.text().replace("CNY", "").trim());
			infoList.add(leave3.text());
			retMap.put(baAdapter.BUSINESS, infoList);
			isThrows = false;
		}
		if(isThrows){
			if(type == baAdapter.GO){
				throw new NoTicketException("去程票已售完");
			} else {
				throw new NoTicketException("回程票已售完");
			}
		}
		
		return retMap;
	}
	
	/**
	 * 点击最低价radio
	 * @param researchPage
	 * @param boundFlightList
	 * @return
	 * @throws IOException
	 */
	private String onclickLowestPriceRadioValue(HtmlPage researchPage, Element boundFlightList) throws IOException {
		
		Elements col1 = boundFlightList.select("td.price-M").select("span.priceSelection");
		
		if(col1 != null && col1.size() != 0){
			
			return "M-1";
		}
		
		Elements col2 = boundFlightList.select("td.price-W").select("span.priceSelection");
		if(col2 != null && col2.size() != 0){
			return "W-1";
		}
		
		Elements col3 = boundFlightList.select("td.price-C").select("span.priceSelection");
		if(col3 != null && col3.size() != 0){
			return "C-1";
		}
		
		return null;
	}
	
	private HtmlPage onclickLowestPriceRadio(HtmlPage researchPage, Element boundFlightList) throws IOException {
		
		Elements col1 = boundFlightList.select("td.price-M").select("span.priceSelection");
		
		if(col1 != null && col1.size() != 0){
//			researchPage=clickGoRadioButton(researchPage, "bound-M-1");System.out.println(researchPage.asXml());
			HtmlRadioButtonInput inRadioButton=null;
			HtmlSubmitInput inRadioButtons=null;
			HtmlPage researchPages=null;
			HtmlForm researchPageForm=(HtmlForm)researchPage.getElementById("flightList");
			System.out.println(researchPageForm.getInputByName("").getValueAttribute());
			inRadioButton=(HtmlRadioButtonInput) researchPageForm.getPage().getElementById("inbound-M-1");
			researchPages=inRadioButton.click();
			try {
				Thread.sleep(1000);
				inRadioButtons=(HtmlSubmitInput)researchPageForm.getPage().getElementById("continue");
				researchPages=inRadioButtons.click();
				System.out.println(researchPages.asXml());
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
			return this.clickRadioButton(researchPage, "bound-M-1");
		}
		
		Elements col2 = boundFlightList.select("td.price-W").select("span.priceSelection");
		if(col2 != null && col2.size() != 0){
			
			HtmlRadioButtonInput inRadioButton=null;
			HtmlSubmitInput inRadioButtons=null;
			HtmlPage researchPages=null;
			HtmlForm researchPageForm=(HtmlForm)researchPage.getElementById("flightList");
			inRadioButton=(HtmlRadioButtonInput) researchPageForm.getPage().getElementById("inbound-W-1");
			researchPages=inRadioButton.click();
			try {
				System.out.println(researchPages.asText());
				Thread.sleep(1000);
				inRadioButtons=(HtmlSubmitInput)researchPageForm.getPage().getElementById("continue");
				researchPages=inRadioButtons.click();
				
				System.out.println(researchPages.asXml());
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
			return this.clickRadioButton(researchPage, "bound-W-1");
		}
		
		Elements col3 = boundFlightList.select("td.price-C").select("span.priceSelection");
		if(col3 != null && col3.size() != 0){
			return this.clickRadioButton(researchPage, "bound-C-1");
		}
		
		return null;
	}
	
	private HtmlPage clickGoRadioButton(HtmlPage researchPage, String clickedRadio)
			throws IOException {
		HtmlRadioButtonInput radioButton = (HtmlRadioButtonInput) researchPage.getElementById("out" + clickedRadio);
		return (HtmlPage) radioButton.click();
	}
	
	private HtmlPage clickRadioButton(HtmlPage researchPage, String clickedRadio)
			throws IOException {
		HtmlRadioButtonInput radioButton = (HtmlRadioButtonInput) researchPage
				.getElementById("in" + clickedRadio);
		return (HtmlPage) radioButton.click();
	}
	
	private HtmlPage parseFlightPopUp(Elements flightPopUp) throws FailingHttpStatusCodeException, MalformedURLException, IOException {
		
		return webClient.getPage("http://www.britishairways.com/main/ba18.jsp/FLIGHTINFORMATION?" + spliteFlightPopUpParams(flightPopUp));
	}
	
	private String spliteFlightPopUpParams(Elements flightPopUp){
		StringBuffer sb = new StringBuffer("");
		
		String carrier = flightPopUp.select("span.Carrier").html();
		String flightNumber = flightPopUp.select("span.FlightNumber").html();
		String from = flightPopUp.select("span.from").html();
		String to = flightPopUp.select("span.to").html();
		String depDate = flightPopUp.select("span.depDate").html();
		String connectingFlightFlag = flightPopUp.select("span.ConnectingFlightFlag").html();
		String economySellingClass = flightPopUp.select("span.EconomySellingClass").html();
		String premiumEconomySellingClass = flightPopUp.select("span.PremiumEconomySellingClass").html();
		String businessSellingClass = flightPopUp.select("span.BusinessSellingClass").html();
		
		sb.append("Carrier=").append(carrier)
		.append("&FlightNumber=").append(flightNumber)
		.append("&from=").append(from)
		.append("&to=").append(to)
		.append("&depDate=").append(depDate)
		.append("&ConnectingFlightFlag=").append(connectingFlightFlag)
		.append("&EconomySellingClass=").append(economySellingClass)
		.append("&PremiumEconomySellingClass=").append(premiumEconomySellingClass)
		.append("&BusinessSellingClass=").append(businessSellingClass)
		;
		return sb.toString();
	}
	
//	private String retHtml(GetMethod get) throws IOException,
//			UnsupportedEncodingException {
//		InputStream in = get.getResponseBodyAsStream();
//		int count = -1;
//		int bufferSize = 1024 * 2;
//		ByteArrayOutputStream outStream = new ByteArrayOutputStream();
//		byte[] data = new byte[bufferSize];
//		while ((count = in.read(data, 0, bufferSize)) != -1)
//			outStream.write(data, 0, count);
//		String retStr = new String(outStream.toByteArray(), get.getResponseCharSet());
//		return retStr;
//	}
//	
//	private String retHtml(PostMethod post) throws IOException,
//			UnsupportedEncodingException {
//		InputStream in = post.getResponseBodyAsStream();
//		int count = -1;
//		int bufferSize = 1024 * 2;
//		ByteArrayOutputStream outStream = new ByteArrayOutputStream();
//		byte[] data = new byte[bufferSize];
//		while ((count = in.read(data, 0, bufferSize)) != -1)
//			outStream.write(data, 0, count);
//		String retStr = new String(outStream.toByteArray(),
//				post.getResponseCharSet());
//		return retStr;
//	}
//	
//	private NameValuePair[] spliteFirstLayArray(HtmlForm form){
//		List<NameValuePair> list = new ArrayList<NameValuePair>();
//		
//		String depDate = "";
//		String retDate = "";
//		try {
//			depDate = "05/09/14";//DateUtil.String2String(taskQueue.getFlightDate(), "yyyy-MM-dd", "DD/MM/YY");
//			retDate = "20/09/14";//DateUtil.String2String(taskQueue.getFlightDate(), "yyyy-MM-dd", "DD/MM/YY");
//		} catch (Exception e) {
//			// TODO Auto-generated catch block
//			e.printStackTrace();
//		}
//		list.add(new NameValuePair("eId", form.getInputByName("eId").getValueAttribute()));
//		list.add(new NameValuePair("saleOption", form.getInputByName("saleOption").getValueAttribute()));
//		list.add(new NameValuePair("depCountry", form.getSelectByName("depCountry").getDefaultValue()));
//		list.add(new NameValuePair("from", "PEK"/*taskQueue.getFromCity()*/));
//		list.add(new NameValuePair("journeyType", form.getInputByName("journeyType").getValueAttribute()));
//		list.add(new NameValuePair("to", "LHR"/*taskQueue.getToCity()*/));
//		list.add(new NameValuePair("depDate", depDate));
//		list.add(new NameValuePair("retDate", retDate));
//		list.add(new NameValuePair("cabin", "M"));//只取经济舱，即可得到最低价
//		list.add(new NameValuePair("restrictionType", form.getInputByName("restrictionType").getValueAttribute()));
//		list.add(new NameValuePair("ad", "1"));//成人人数
//		list.add(new NameValuePair("ch", "0"));//儿童人数
//		list.add(new NameValuePair("inf", "0"));//婴儿数
//		return list.toArray(new NameValuePair[list.size()]);
//	}
//
	private Map<String, String> spliteFirstLayMap(HtmlForm form){
		Map<String, String> map = new HashMap<String, String>();
		String depDate = "";
		String retDate = "";
		try {
			depDate = DateUtil.String2String(taskQueue.getFlightDate(), "yyyy-MM-dd", "dd/MM/yy");
			retDate = DateUtil.String2String(taskQueue.getReturnGrabDate(), "yyyy-MM-dd", "dd/MM/yy");
		} catch (Exception e) {
			e.printStackTrace();
		}
		map.put("eId", form.getInputByName("eId").getValueAttribute());
		map.put("saleOption", form.getInputByName("saleOption").getValueAttribute());
		map.put("depCountry", form.getSelectByName("depCountry").getDefaultValue());
		map.put("from", taskQueue.getFromCity());
		map.put("journeyType", form.getInputByName("journeyType").getValueAttribute());
		map.put("to", taskQueue.getToCity());
		map.put("depDate", depDate);
		map.put("retDate", retDate);
		map.put("cabin", "M");//只取经济舱，即可得到最低价
		if(isHomePageEnter){
			map.put("restrictionType", form.getSelectByName("restrictionType").getDefaultValue());
		} else {
			map.put("restrictionType", form.getInputByName("restrictionType").getValueAttribute());
		}
		
		map.put("ad", "1");//成人人数
		map.put("ch", "0");//儿童人数
		map.put("inf", "0");//婴儿数
		return map;
	}
	
	private Map<String, String> spliteFirstLayMap2(HtmlForm form){
		Map<String, String> map = new HashMap<String, String>();

		map.put("continue", "%E7%BB%A7%E7%BB%AD");
		map.put("source", "continue");
		map.put("eId", "111011");
		map.put("eIdSortBy", "");
		map.put("inbound", "W-1");
		map.put("inboundCabin", "W");
		map.put("outbound", "C-1");
		map.put("outboundCabin", "C");
		map.put("inboundHLAFlag", "true");
		map.put("isHBOPage", "false");
		map.put("syncIndicator-inbound", "on");
		map.put("syncIndicator-outbound", "on");
		return map;
	}
	
}
